package controllers

import (
	"egin/app/request"
	"egin/app/service"
	"egin/pkg/redigo"
	"egin/pkg/response"
	"egin/pkg/vali"
	"encoding/json"
	"net/http"
	"strconv"

	"github.com/garyburd/redigo/redis"
	"github.com/go-playground/validator/v10"

	"github.com/gin-contrib/sessions"

	"egin/pkg/captcha"

	"github.com/gin-gonic/gin"
)

const PASSWRODERRORSCOUNT = 3

//存储验证码的结构
type CaptchaResult struct {
	Id         string `json:"id"`
	Base64Blob string `json:"base_64_blob"`
}

//LoginHTML 登陆页面
func LoginHTML(c *gin.Context) {

	c.HTML(http.StatusOK, "login/login.tmpl", nil)
}

//CaptchaImage 验证码
func CaptchaImage(c *gin.Context) {

	captchaId, b64s, _ := captcha.CaptMake()

	captchaResult := CaptchaResult{
		Id:         captchaId,
		Base64Blob: b64s,
	}

	response.SuccessWithData(captchaResult, c)

}

//Login 登陆
func Login(c *gin.Context) {

	var param request.Loegintruct
	if err := c.ShouldBind(&param); err != nil {

		errStr := vali.ValidErrMsg(&param, err.(validator.ValidationErrors))
		response.ErrorWithMessage(errStr, c)
		return
	}

	// /*fmt.println(username)*/
	// //判断验证码
	res := service.VerfiyCaptcha(param.CaptchaId, param.Captcha)
	if !res {
		response.ErrorWithMessage("验证码错误", c)
		return
	}

	resL, userInfo := service.Login(param)
	var key string
	if userInfo.ID == 0 {
		key = "passworderrorsnumber-" + c.ClientIP()
	} else {
		key = "passworderrorsnumber-" + strconv.Itoa((int(userInfo.ID)))
	}

	conn := redigo.GetPool().Get()
	defer conn.Close()

	num, _ := redis.Int(conn.Do("get", key))
	if num > PASSWRODERRORSCOUNT-1 {
		response.ErrorWithMessage("账户或者密码错误"+strconv.Itoa(PASSWRODERRORSCOUNT)+"次，24小时后再试", c)
		return
	}

	if !resL {
		num++
		conn.Do("set", key, num)
		if num >= PASSWRODERRORSCOUNT {
			conn.Do("EXPIRE", key, 3600*24)
			response.ErrorWithMessage("账户或者密码错误"+strconv.Itoa(PASSWRODERRORSCOUNT)+"次，24小时后再试", c)
		} else {
			response.ErrorWithMessage("账户或者密码错误,还有"+strconv.Itoa(PASSWRODERRORSCOUNT-num)+"次机会", c)
		}

		return
	}

	conn.Do("del", key)

	userid := int(userInfo.ID)
	session := sessions.Default(c)
	session.Set("id", strconv.Itoa(userid))
	userjson, err := json.Marshal(userInfo)
	if err == nil {
		session.Set("member_info", string(userjson))
	}
	if err := session.Save(); err == nil {
		response.SuccessWithMessage("登录成功", c)
	} else {
		response.ErrorWithMessage("登录成功失败", c)
	}

}

//Unlock 解锁
func Unlock(c *gin.Context) {

	var param request.UnlockStruct
	if err := c.ShouldBind(&param); err != nil {
		errStr := vali.ValidErrMsg(&param, err.(validator.ValidationErrors))
		response.ErrorWithMessage(errStr, c)
		return
	}

	session := sessions.Default(c)
	num := session.Get("passworderrorsnumber")
	numint := 0
	if num != nil {
		numint, _ = strconv.Atoi(num.(string))
	}

	if numint > PASSWRODERRORSCOUNT-1 {
		response.ErrorWithMessage("密码错误"+strconv.Itoa(PASSWRODERRORSCOUNT)+"次，需要重新登陆", c)
		return
	}

	if ok := service.Unlock(c, param); ok {
		session.Delete("passworderrorsnumber")
		session.Save()

		response.SuccessWithMessage("解锁成功", c)
	} else {

		numint++
		session.Set("passworderrorsnumber", strconv.Itoa(numint))
		session.Save()
		if numint >= PASSWRODERRORSCOUNT {
			response.ErrorWithMessage("密码错误"+strconv.Itoa(PASSWRODERRORSCOUNT)+"次，需要重新登陆", c)
		} else {
			response.ErrorWithMessage("密码错误,还有"+strconv.Itoa(PASSWRODERRORSCOUNT-numint)+"次机会", c)
		}

	}

}

//logout 退出登陆
func Logout(c *gin.Context) {
	session := sessions.Default(c)
	session.Clear()
	if err := session.Save(); err == nil {
		conn := redigo.GetPool().Get()
		defer conn.Close()

		conn.Do("hdel", "admin_rbac", session.Get("id"))
		conn.Do("hdel", "admin_menu", session.Get("id"))

		response.SuccessWithMessage("退出登录", c)
	} else {
		response.ErrorWithMessage("退出登录失败", c)
	}

}
